home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 020a / dvpt20.zip / VRMOD.ASM < prev    next >
Assembly Source File  |  1991-12-12  |  15KB  |  723 lines

  1. page 58,132
  2. ;****************************************************************
  3. ;*                                                              *
  4. ;*             Digitized Voice Programmer's Toolkit             *
  5. ;*             ------------------------------------             *
  6. ;*                                                              *
  7. ;*                 Sound Recording Primitives                   *
  8. ;*                                                              *
  9. ;*            Copyright (c) 1991, Farpoint Software             *
  10. ;*                                                              *
  11. ;****************************************************************
  12.  
  13. .8086
  14. .MODEL LARGE
  15.  
  16. ;**********************************************************************
  17. ;*                                                                    *
  18. ;*                             Equates                                *
  19. ;*                                                                    *
  20. ;**********************************************************************
  21.  
  22. tccount        equ    72    ;reload count to produce 16572 Hz
  23. countmax_18hz    equ    910    ;ratio of new timer rate to standard rate
  24.  
  25. tcaddrc        equ    43h    ;timer/counter control register address
  26. tcaddrd0    equ    40h    ;timer/counter data register zero (sys clock)
  27.  
  28. tcmode0a    equ    34h    ;two-byte mode for system clock timer
  29. tcmode0b    equ    24h    ;high-byte mode for system clock timer
  30.  
  31. tclatchcmd0    equ    00h    ;latch command for reading timer 0
  32.  
  33. ppiaddr        equ    61h    ;programmable peripheral interface address
  34.  
  35. kbdonly_mask    equ    0FDh    ;mask config to allow only keyboard interrupt
  36. intmaskaddr    equ    21h    ;address of the interrupt mask register
  37. kbdint_number    equ    9    ;vector number of the keyboard hardware int
  38.  
  39. ;CPU speed calibration initialization parameters
  40.  
  41. init_delayctr        equ    1024
  42. init_cal_increment    equ    512
  43. init_cal_passes        equ    10
  44.  
  45. ;**********************************************************************
  46. ;*                                                                    *
  47. ;*                         Global variables                           *
  48. ;*                                                                    *
  49. ;**********************************************************************
  50.  
  51. .DATA
  52.  
  53. comaddr        dw    2ECh
  54.  
  55. ;CPU speed calibration data
  56.  
  57. delayctr    dw    init_delayctr
  58. cal_increment    dw    init_cal_increment
  59. cal_passes    dw    init_cal_passes
  60.  
  61. ;keyboard hardware interrupt occurrence flag
  62.  
  63. keyflag        db    0
  64.  
  65. ;interrupt controller mask save byte
  66.  
  67. original_mask    db    0
  68.  
  69. comlist        dw    3FCh    ;needed addresses of all COM ports
  70.         dw    2FCh
  71.         dw    3ECh
  72.         dw    2ECh
  73.  
  74. ;**********************************************************************
  75. ;*                                                                    *
  76. ;*                               Code                                 *
  77. ;*                                                                    *
  78. ;**********************************************************************
  79.  
  80. .CODE
  81.  
  82.     assume    ds:DGROUP
  83.  
  84. ;code-segment storage for keyboard interrupt chain vector
  85.  
  86. original_kbdint_vec    dd    0
  87.  
  88. ;**********************************************************************
  89. ;*          Keyboard Hardware Interrupt Intercept Routine             *
  90. ;**********************************************************************
  91.  
  92. ;This routine sets the "keyflag" variable to 1 whenever a keyboard
  93. ; interrupt occurs.
  94.  
  95. kbdint    proc    far
  96.  
  97.     push    ds
  98.     push    ax
  99.     mov    ax,DGROUP
  100.     mov    ds,ax
  101.     mov    keyflag,1
  102.     pop    ax
  103.     pop    ds
  104.     jmp    dword ptr cs:original_kbdint_vec
  105.  
  106. kbdint    endp
  107.  
  108. ;**********************************************************************
  109. ;*            Obtain available memory figure from DOS                 *
  110. ;**********************************************************************
  111.  
  112. ;This routine returns a dword indicating the number of bytes of memory
  113. ; available for allocation from DOS.
  114.  
  115.     public    GETMEMAVAIL
  116.  
  117. GETMEMAVAIL    proc    far
  118.  
  119.     push    bp
  120.     mov    bp,sp
  121.  
  122.     mov    bx,0FFFFh
  123.     mov    ah,48h
  124.     int    21h
  125.     sub    bx,16
  126.     jc    gma_none
  127.     sub    dx,dx
  128.     mov    ax,bx
  129.     mov    cx,4
  130. gma_dshift:
  131.     shl    ax,1
  132.     rcl    dx,1
  133.     loop    gma_dshift
  134.  
  135. gma_exit:
  136.     pop    bp
  137.     ret
  138.  
  139. gma_none:
  140.     sub    ax,ax
  141.     sub    dx,dx
  142.     jmp    gma_exit
  143.  
  144. GETMEMAVAIL    endp
  145.  
  146. ;**********************************************************************
  147. ;*              Calibrated software delay routine                     *
  148. ;**********************************************************************
  149.  
  150. ;lots of nops
  151.  
  152. rdelay    proc    near
  153.  
  154.     db    init_delayctr dup (90h)
  155.     ret                ;starting delay value
  156.     db    (init_delayctr-1) dup (90h)
  157.     ret                ;should never actually be executed
  158.  
  159. rdelay    endp
  160.  
  161. ;**********************************************************************
  162. ;*                    Set Calibration Constant                        *
  163. ;*                                                                    *
  164. ;*       This call simply sets the calibration constant to the        *
  165. ;*       value specified in the parameter.                            *
  166. ;**********************************************************************
  167.  
  168. ;Accepts the following parameters with PASCAL parameter-passing convention:
  169.  
  170. ;Position   Size   Description
  171. ;--------   ----   -----------
  172. ;   1         2    The calibration constant to be set.
  173.  
  174. ;There is no return value.
  175.  
  176. rsc_parm1    equ    [bp+6]    ;length = 2
  177.  
  178. rsc_parmlength    equ    2
  179.  
  180.     public    RSETCAL
  181.  
  182. RSETCAL        proc    far
  183.  
  184.     push    bp
  185.     mov    bp,sp
  186.  
  187. ;in case this routine has been called before, erase the "ret" instruction
  188. ; that was placed in the delay routine
  189.  
  190.     lea    bx,rdelay
  191.     add    bx,delayctr
  192.     mov    byte ptr cs:[bx],90h    ;this is a "nop" instruction
  193.  
  194. ;get the new delay parameter
  195.  
  196.     mov    ax,rsc_parm1
  197.     mov    delayctr,ax
  198.  
  199. ;insert a "ret" instruction at the new location in the delay routine
  200.  
  201.     lea    bx,rdelay
  202.     add    bx,delayctr
  203.     mov    byte ptr cs:[bx],0C3h    ;this is a "ret" instruction
  204.  
  205.     pop    bp
  206.     ret    rsc_parmlength
  207.  
  208. RSETCAL        endp
  209.  
  210. ;**********************************************************************
  211. ;*                      Calibration procedure                         *
  212. ;*                                                                    *
  213. ;*      This routine must be called once before any calls are made    *
  214. ;*      to the recording routine. It measures the CPU execution       *
  215. ;*      speed and saves compensation values.                          *
  216. ;**********************************************************************
  217.  
  218. ;There are no entry parameters.
  219.  
  220. ;The return value is a double word, defined as follows:
  221.  
  222. ;Return value low word        Meaning
  223. ;---------------------        -------
  224. ;     0                       success
  225. ;     1                       this CPU is too slow to accomplish
  226. ;                              normal-speed playback
  227. ;     2                       operation not possible under Windows
  228. ;                              in "Enhanced" mode
  229.  
  230. ;The return value high word is the actual speed calibration constant
  231. ; for this computer
  232.  
  233. cal_temp1        equ    [bp-2]    ;length = 2
  234. cal_temp2        equ    [bp-4]    ;length = 2
  235.  
  236. cal_locallength        equ    4
  237.  
  238.     public    RCALIBRATE
  239.  
  240. RCALIBRATE    proc    far
  241.  
  242.     push    bp
  243.     mov    bp,sp
  244.     sub    sp,cal_locallength
  245.     push    si
  246.  
  247. ;test for the "Enhanced Mode Windows" environment
  248.  
  249.     mov    ax,1600h
  250.     int    2Fh
  251.     cmp    al,00h
  252.     je    cal_no_enh_win
  253.     cmp    al,80h
  254.     je    cal_no_enh_win
  255.     mov    delayctr,1
  256.     mov    ax,2
  257.     jmp    cal_exit
  258. cal_no_enh_win:
  259.  
  260. ;in case this routine has been called before, erase the "ret" instruction
  261. ; that was placed in the delay routine
  262.  
  263.     lea    bx,rdelay
  264.     add    bx,delayctr
  265.     mov    byte ptr cs:[bx],90h    ;this is a "nop" instruction
  266.  
  267. ;initialize parameters
  268.  
  269.     mov    delayctr,init_delayctr
  270.     mov    cal_increment,init_cal_increment
  271.     mov    cal_passes,init_cal_passes
  272.  
  273. ;insert a "ret" instruction into the starting location in the delay routine
  274.  
  275.     lea    bx,rdelay
  276.     add    bx,delayctr
  277.     mov    byte ptr cs:[bx],0C3h    ;this is a "ret" instruction
  278.  
  279. ;no interrupts until we are through calibrating
  280.  
  281.     cli
  282.  
  283. ;write the standard setup to timer zero
  284.  
  285.     mov    al,tcmode0a
  286.     out    tcaddrc,al
  287.     jmp    short $+2
  288.     jmp    short $+2
  289.     mov    al,0
  290.     out    tcaddrd0,al
  291.     jmp    short $+2
  292.     jmp    short $+2
  293.     out    tcaddrd0,al
  294.     jmp    short $+2
  295.     jmp    short $+2
  296.  
  297. ;set timer zero to high-byte mode
  298.  
  299.     mov    al,tcmode0b
  300.     out    tcaddrc,al
  301.     jmp    short $+2
  302.     jmp    short $+2
  303.     mov    al,0
  304.     out    tcaddrd0,al
  305.     jmp    short $+2
  306.     jmp    short $+2
  307.  
  308. ;use a "dummy" port address
  309.  
  310.     mov    dx,comaddr
  311.  
  312. ;initialize loop count
  313.  
  314. cal_zerocnt:
  315.     sub    cx,cx
  316.     mov    word ptr cal_temp1,0
  317.     mov    word ptr cal_temp2,0
  318.     mov    keyflag,0
  319.  
  320. ;synchronize to timer tick
  321.  
  322.     mov    ah,0
  323.     mov    al,tclatchcmd0
  324.     out    tcaddrc,al
  325.     jmp    short $+2
  326.     jmp    short $+2
  327.     in    al,tcaddrd0
  328.     jmp    short $+2
  329.     jmp    short $+2
  330.     mov    si,ax
  331. cal_sync:
  332.     mov    al,tclatchcmd0
  333.     out    tcaddrc,al
  334.     jmp    short $+2
  335.     jmp    short $+2
  336.     in    al,tcaddrd0
  337.     jmp    short $+2
  338.     cmp    ax,si
  339.     mov    si,ax
  340.     jbe    cal_sync
  341.  
  342. ;calibration loop
  343.  
  344. cal_dummyloop:
  345.     mov    al,01h
  346.     out    dx,al
  347.     jmp    short $+2
  348.     jmp    short $+2
  349.     add    dx,2
  350.     in    al,dx
  351.     shr    al,1
  352.     shr    al,1
  353.     shr    al,1
  354.     shr    al,1
  355.     mov    ah,al
  356.     sub    dx,2
  357.     mov    al,00h
  358.     out    dx,al
  359.     jmp    short $+2
  360.     jmp    short $+2
  361.     add    dx,2
  362.     in    al,dx
  363.     and    al,0F0h
  364.     or    ah,al
  365.     mov    al,02h
  366.     sub    dx,2
  367.     out    dx,al
  368.     jmp    short $+2
  369.     jmp    short $+2
  370.     jmp    short $+2
  371.     jmp    short $+2
  372.     jmp    short $+2
  373.     jmp    short $+2
  374.     mov    al,00h
  375.     out    dx,al
  376.     inc    cx
  377.     jnz    cal_countbytes
  378. cal_countbytes:
  379.     inc    word ptr cal_temp2
  380.     jnz    cal_dummydelay
  381.     inc    word ptr cal_temp1
  382. cal_dummydelay:
  383.     call    rdelay
  384.     inc    dx
  385.     in    al,dx
  386.     dec    dx
  387.     test    al,00h        ;dummy test for end of recording
  388.     jnz    cal_checktime
  389.     cmp    keyflag,0
  390.     jne    cal_checktime
  391. cal_checktime:
  392.     mov    al,tclatchcmd0
  393.     out    tcaddrc,al
  394.     jmp    short $+2
  395.     jmp    short $+2
  396.     in    al,tcaddrd0
  397.     sub    ah,ah
  398.     cmp    ax,si
  399.     mov    si,ax
  400.     jbe    cal_dummyloop
  401.  
  402. ;kill the old "ret" instruction in the delay routine
  403.  
  404.     lea    bx,rdelay
  405.     add    bx,delayctr
  406.     mov    byte ptr cs:[bx],90h    ;this is a "nop" instruction
  407.  
  408. ;adjust delay counter
  409.  
  410.     mov    ax,cal_increment
  411.     shr    cal_increment,1
  412.     cmp    cx,countmax_18hz
  413.     je    cal_setret
  414.     jb    cal_makefaster
  415.     add    delayctr,ax
  416.     jmp    cal_setret
  417. cal_makefaster:
  418.     sub    delayctr,ax
  419. cal_setret:                ;here we insert a new return
  420.     lea    bx,rdelay
  421.     add    bx,delayctr
  422.     mov    byte ptr cs:[bx],0C3h    ;this is a "ret" instruction
  423.     dec    cal_passes
  424.     cmp    cal_passes,0
  425.     je    cal_restore
  426.     jmp    cal_zerocnt
  427.  
  428. ;repair loss of system timer ticks and restore interrupts
  429.  
  430. cal_restore:
  431.     mov    bx,40h
  432.     mov    es,bx
  433.     mov    bx,6Ch
  434.     add    word ptr es:[bx],init_cal_passes+1
  435.     adc    word ptr es:[bx+2],0
  436.     cmp    word ptr es:[bx+2],18h
  437.     jb    cal_tc_end
  438.     ja    cal_tc_midnite
  439.     cmp    word ptr es:[bx],0B0h
  440.     jb    cal_tc_end
  441. cal_tc_midnite:
  442.     mov    byte ptr es:[bx+4],1
  443.     sub    word ptr es:[bx],0B0h
  444.     sbb    word ptr es:[bx+2],18h
  445. cal_tc_end:
  446.     sti
  447.  
  448. ;determine if CPU is too slow
  449.  
  450. cal_checkcpu:
  451.     cmp    delayctr,1
  452.     je    cal_cpuslow
  453.     sub    ax,ax
  454.     jmp    cal_exit
  455. cal_cpuslow:
  456.     mov    ax,1
  457. cal_exit:
  458.     mov    dx,delayctr
  459.     pop    si
  460.     add    sp,cal_locallength
  461.     pop    bp
  462.     ret
  463.  
  464. RCALIBRATE    endp
  465.  
  466. ;**********************************************************************
  467. ;*                         Record procedure                           *
  468. ;**********************************************************************
  469.  
  470. ;Accepts the following parameters with PASCAL parameter-passing convention:
  471.  
  472. ;Position   Size   Description
  473. ;--------   ----   -----------
  474. ;   1         4    A far pointer to the memory block used for voice data.
  475. ;   2         4    A dword indicating the length of the memory block.
  476. ;   3         2    A word containing the number of the COM port to be used
  477. ;                   for input (1 thru 4).
  478.  
  479. ;The return value is a dword indicating the number of bytes recorded.
  480. ;A return value of -1L indicates that the COM port was invalid.
  481.  
  482. ;A full buffer or a break interrupt from the UART stops the recording.
  483.  
  484. rv_parm1        equ    [bp+12]    ;length = 4
  485. rv_parm2hi        equ    [bp+10]    ;length = 2
  486. rv_parm2lo        equ    [bp+8]    ;length = 2
  487. rv_parm3        equ    [bp+6]    ;length = 2
  488.  
  489. rv_parmlength        equ    10
  490.  
  491. rv_temp1        equ    [bp-2]    ;length = 2
  492. rv_temp2        equ    [bp-4]    ;length = 2
  493.  
  494. rv_locallength        equ    4
  495.  
  496.     public    RECORDVOICE
  497.  
  498. RECORDVOICE    proc    far
  499.  
  500.     push    bp
  501.     mov    bp,sp
  502.     sub    sp,rv_locallength
  503.     push    si
  504.  
  505. ;set up com port
  506.  
  507.     mov    dx,rv_parm3
  508.     cmp    dx,1
  509.     jae    rv_comhirange
  510.     jmp    rv_badcom
  511. rv_comhirange:
  512.     cmp    dx,4
  513.     jbe    rv_lookupcomaddress
  514.     jmp    rv_badcom
  515. rv_lookupcomaddress:
  516.     dec    dx
  517.     shl    dx,1
  518.     lea    bx,comlist
  519.     add    bx,dx
  520.     mov    dx,[bx]
  521.     mov    comaddr,dx
  522.  
  523.     sub    dx,4
  524.     in    al,dx
  525.     jmp    short $+2
  526.     jmp    short $+2
  527.     in    al,dx
  528.     jmp    short $+2
  529.     jmp    short $+2
  530.     in    al,dx
  531.     jmp    short $+2
  532.     jmp    short $+2
  533.     add    dx,2
  534.     in    al,dx
  535.     jmp    short $+2
  536.     jmp    short $+2
  537.     add    dx,3
  538.     in    al,dx
  539.     jmp    short $+2
  540.     jmp    short $+2
  541.     inc    dx
  542.     in    al,dx
  543.     sub    dx,2
  544.  
  545. ;mask all interrupts except the keyboard
  546.  
  547.     cli
  548.  
  549.     in    al,intmaskaddr
  550.     mov    original_mask,al
  551.     mov    al,kbdonly_mask
  552.     out    intmaskaddr,al
  553.  
  554. ;install the keyboard interrupt intercept routine
  555.  
  556.     sub    ax,ax
  557.     mov    es,ax
  558.     mov    bx,kbdint_number*4
  559.     mov    ax,es:[bx]
  560.     mov    word ptr cs:original_kbdint_vec,ax
  561.     mov    ax,es:[bx+2]
  562.     mov    word ptr cs:original_kbdint_vec+2,ax
  563.     lea    ax,kbdint
  564.     mov    es:[bx],ax
  565.     mov    ax,cs
  566.     mov    es:[bx+2],ax
  567.  
  568.     sti
  569.  
  570. ;set up initial conditions
  571.  
  572.     mov    word ptr rv_temp1,0
  573.     mov    word ptr rv_temp2,0
  574.     mov    keyflag,0
  575.     les    bx,dword ptr rv_parm1
  576.     mov    cx,rv_parm2lo
  577.     mov    si,rv_parm2hi
  578.     cmp    cx,0
  579.     je    rv_recordloop
  580.     inc    si
  581.  
  582. ;recording loop
  583.  
  584. rv_recordloop:
  585.     mov    al,01h
  586.     out    dx,al
  587.     jmp    short $+2
  588.     jmp    short $+2
  589.     add    dx,2
  590.     in    al,dx
  591.     shr    al,1
  592.     shr    al,1
  593.     shr    al,1
  594.     shr    al,1
  595.     mov    ah,al
  596.     sub    dx,2
  597.     mov    al,00h
  598.     out    dx,al
  599.     jmp    short $+2
  600.     jmp    short $+2
  601.     add    dx,2
  602.     in    al,dx
  603.     and    al,0F0h
  604.     or    ah,al
  605.     mov    al,02h
  606.     sub    dx,2
  607.     out    dx,al
  608.     jmp    short $+2
  609.     jmp    short $+2
  610.     jmp    short $+2
  611.     jmp    short $+2
  612.     jmp    short $+2
  613.     jmp    short $+2
  614.     mov    al,00h
  615.     out    dx,al
  616.     mov    es:[bx],ah
  617.     inc    bx
  618.     jnz    rv_countbytes
  619.     mov    ax,es
  620.     add    ax,1000h
  621.     mov    es,ax
  622. rv_countbytes:
  623.     inc    word ptr rv_temp2
  624.     jnz    rv_delay
  625.     inc    word ptr rv_temp1
  626. rv_delay:
  627.     call    rdelay
  628.     inc    dx
  629.     in    al,dx
  630.     dec    dx
  631.     test    al,10h        ;test for end of recording
  632.     jnz    rv_stop
  633.     cmp    keyflag,0
  634.     jne    rv_stop
  635.     mov    al,tclatchcmd0
  636.     out    tcaddrc,al
  637.     jmp    short $+2
  638.     jmp    short $+2
  639.     in    al,tcaddrd0
  640.     sub    ah,ah
  641.     nop
  642.     nop
  643.     nop
  644.     nop
  645.     nop
  646.     nop
  647.     nop
  648.     nop
  649.     nop
  650.     nop
  651.     nop
  652.     loop    rv_recordloop
  653.     dec    si
  654.     jnz    rv_recordloop
  655. rv_stop:
  656.  
  657. ;remove the keyboard interrupt intercept routine
  658.  
  659.     cli
  660.  
  661.     sub    ax,ax
  662.     mov    es,ax
  663.     mov    bx,kbdint_number*4
  664.     mov    ax,word ptr cs:original_kbdint_vec
  665.     mov    es:[bx],ax
  666.     mov    ax,word ptr cs:original_kbdint_vec+2
  667.     mov    es:[bx+2],ax
  668.  
  669. ;restore the original interrupt mask
  670.  
  671.     mov    al,original_mask
  672.     out    intmaskaddr,al
  673.  
  674.     sti
  675.  
  676. ;compensate for lost timer ticks
  677.  
  678.     mov    dx,rv_parm2hi
  679.     mov    ax,rv_parm2lo
  680.     mov    cx,countmax_18hz
  681.     div    cx
  682.     mov    bx,40h
  683.     mov    es,bx
  684.     mov    bx,6Ch
  685.     cli
  686.     add    es:[bx],ax
  687.     adc    word ptr es:[bx+2],0
  688.     cmp    word ptr es:[bx+2],18h
  689.     jb    rv_tc_end
  690.     ja    rv_tc_midnite
  691.     cmp    word ptr es:[bx],0B0h
  692.     jb    rv_tc_end
  693. rv_tc_midnite:
  694.     mov    byte ptr es:[bx+4],1
  695.     sub    word ptr es:[bx],0B0h
  696.     sbb    word ptr es:[bx+2],18h
  697. rv_tc_end:
  698.     sti
  699.  
  700. ;set return value
  701.  
  702.     mov    dx,rv_temp1
  703.     mov    ax,rv_temp2
  704.  
  705. ;exit
  706.  
  707. rv_exit:
  708.     pop    si
  709.     add    sp,rv_locallength
  710.     pop    bp
  711.     ret    rv_parmlength
  712.  
  713. ;set return value for COM port out of range
  714.  
  715. rv_badcom:
  716.     mov    dx,0FFFFh
  717.     mov    ax,0FFFFh
  718.     jmp    rv_exit
  719.     
  720. RECORDVOICE    endp
  721.  
  722.     end
  723.